package pkg

import (
	"context"
	"encoding/json"
	"net/url"
	"sale-admin/config/redis"
	"sale-admin/internal/define"
	"strings"
	"time"

	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
)

type Wechat struct{}

const (
	DDZC_APPID = "wx4872c186a4754a45" //大道智创 公众号
	APP_SECRET = "50c1c73ffcbf9c9278711750a0c03ff8"
)

const (
	OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?"
	ACCESS_TOKEN_URL     = "https://api.weixin.qq.com/sns/oauth2/access_token?"
	USER_INFO_URL        = "https://api.weixin.qq.com/sns/userinfo?"
)

// 用户授权，获取code
func (Wechat) GetAuthorizeURL(redirectUri, scope, state string) (AuthorizeUrl string) {
	if scope == "" {
		scope = "snsapi_userinfo"
	}

	var URL url.URL
	query := URL.Query()
	query.Add("appid", DDZC_APPID)
	query.Add("redirect_uri", redirectUri)
	query.Add("response_type", "code")
	query.Add("scope", scope)
	query.Add("state", state)

	return OAUTH2_AUTHORIZE_URL + query.Encode() + "#wechat_redirect"
}

// 获取access_token返回值
type AccessTokenRsp struct {
	AccessToken    string `json:"access_token"`    // 网页授权接口调用凭证
	ExpiresIn      int    `json:"expires_in"`      // 调用凭证超时时间，单位（秒）
	RefreshToken   string `json:"refresh_token"`   // 用户刷新token
	Openid         string `json:"openid"`          // 用户唯一标识
	Scope          string `json:"scope"`           // 用户授权的作用域，逗号分隔多个
	IsSnapshotuser int    `json:"is_snapshotuser"` // 是否为快照页模式虚拟账号，只有当用户是快照页模式虚拟账号时返回，值为1
	Unionid        string `json:"unionid"`         // 用户统一标识
}

// 获取access_token
func (Wechat) GetAccessToken(ctx context.Context, code string) (accessToken, openid string) {
	rdb := redis.NewDB()
	AccessTokenInfo, found := rdb.Get(ctx, define.RedisAccessToken+code).Result()
	if found == nil && AccessTokenInfo != "" {
		token := strings.Split(AccessTokenInfo, "&")
		return token[0], token[1]
	}
	var URL url.URL
	query := URL.Query()
	query.Add("appid", DDZC_APPID)
	query.Add("secret", APP_SECRET)
	query.Add("code", code)
	query.Add("grant_type", "authorization_code")

	tokenUrl := ACCESS_TOKEN_URL + query.Encode()
	statusCode, rspBytes, err := helper.Net{}.Request(ctx, "GET", tokenUrl, map[string]string{}, nil)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "get access token error", logx.Any("response", string(rspBytes)), logx.Any("获取授权错误", err.Error()))
		return
	}

	var res AccessTokenRsp
	json.Unmarshal(rspBytes, &res)
	logx.Info(ctx, "get access token success", logx.Any("response", res), logx.Any("bytes", string(rspBytes)))
	if res.AccessToken != "" && res.Openid != "" && res.ExpiresIn > 0 {
		rdb.Set(ctx, define.RedisAccessToken+code, res.AccessToken+"&"+res.Openid, time.Duration(res.ExpiresIn/2)*time.Second)
	}
	return res.AccessToken, res.Openid
}

type GetUserInfoRsp struct {
	Openid     string   `json:"openid"`
	Nickname   string   `json:"nickname"`
	Sex        int      `json:"sex"`
	Province   string   `json:"province"`
	City       string   `json:"city"`
	Country    string   `json:"country"`
	Headimgurl string   `json:"headimgurl"`
	Privilege  []string `json:"privilege"`
	Unionid    string   `json:"unionid"`
}

// 获取用户信息
func (Wechat) GetUserInfo(ctx context.Context, accessToken, openid string) (res GetUserInfoRsp) {
	var URL url.URL
	query := URL.Query()
	query.Add("access_token", accessToken)
	query.Add("openid", openid)
	query.Add("lang", "zh_CN")

	getInfoUrl := USER_INFO_URL + query.Encode()
	statusCode, rspBytes, err := helper.Net{}.Request(ctx, "GET", getInfoUrl, map[string]string{}, nil)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "get user info error", logx.Any("response", string(rspBytes)), logx.Any("获取用户信息错误", err.Error()))
		return
	}

	json.Unmarshal(rspBytes, &res)
	return res
}
